#include "message.h"
#include <iomanip>
#include <iostream>

using namespace std;

Message::Message ( void )
{
	this->message = 0;
	this->binary = 0;
	this->lenght = 0;
	this->binaryLenght = 0;
}

Message::Message ( int lenght, string message, bool hex )
{
	this->lenght = lenght;
	this->message = new unsigned char[lenght];
	strncpy ( (char *) this->message, message.c_str(), lenght );
	
	if ( hex == false )
	{
		/* ASCII code handling. */
		
		this->binaryLenght = lenght * 8;
		this->binary = new bool[lenght * 8];
		AsciiToBinary();
	}
	else
	{
		/* HEX code handling. */

		this->binaryLenght = lenght * 4;
		this->binary = new bool[lenght * 4];	
		HexToBinary();
	}
}

void Message::AsciiToBinary ( void )
{
	int i, j, k;
	unsigned char ch;
	bool *binary;

	for ( i = 0, j = 0; i < lenght; i++, j += 8 )
	{
		ch = this->message[i];
		binary = &(this->binary[j]);

		for ( k = 0; k < 8; k++ )
		{
			switch ( ch % 2 )
			{
				case 0:
					binary [ 7 - k ] = false;
					break;
				case 1:
					binary [ 7 - k ] = true;
					break;
			}

			ch = ch / 2;	
		}
	}
}




void Message::HexToBinary ( void )
{
	int i, j;

	for ( i = 0, j = 0; j < binaryLenght; i++, j += 4 )
	{
		if ( message[i] == '0' )
		{
			//0 0 0 0
			binary[j] = binary[ j + 1] = binary[j + 2] = binary[j + 3] = false;
		}
		else if ( message[i] == '1' )
		{
			//0 0 0 1
			binary[j] = binary[j + 1] = binary[j + 2] = false;
			binary[j + 3] = true;
		}
		else if ( message[i] == '2' )
		{
			//0 0 1 0
			binary[j] = binary[j + 1] = binary[j + 3] = false;
			binary[j + 2] = true;
		}
		else if ( message[i] == '3' )
		{
			//0 0 1 1
			binary[j] = binary[j + 1] = false;
			binary[j + 2] = binary[j + 3] = true;
		}
		else if ( message[i] == '4' )
		{
			//0 1 0 0
			binary[j] = binary[j + 2] = binary[j + 3] = false;
			binary[j + 1] = true;
		}
		else if ( message[i] == '5' )
		{
			//0 1 0 1
			binary[j] = binary[j + 2] = false;
			binary[j + 1] = binary[j + 3] = true;
		}
		else if ( message[i] == '6' )
		{
			//0 1 1 0
			binary[j] = binary[j + 3] = false;
			binary[j + 1] = binary[j + 2] = true;
		}
		else if ( message[i] == '7' )
		{
			//0 1 1 1
			binary[j] = false;
			binary[j + 1] = binary[j + 2]= binary[j + 3] = true;
		}
		else if ( message[i] == '8' )
		{
			//1 0 0 0
			binary[j] = true;
			binary[j + 1] = binary[j + 2]= binary[j + 3] = false;
		}
		else if ( message[i] == '9' )
		{
			//1 0 0 1
			binary[j] = binary[j + 3] = true;
			binary[j + 1] = binary[j + 2] = false;
		}
		else if ( message[i] == 'a' )
		{
			//1 0 1 0
			binary[j] = binary[j + 2] = true;
			binary[j + 1] = binary[j + 3] = false;
		}
		else if ( message[i] == 'b' )
		{
			//1 0 1 1
			binary[j + 1] = false;
			binary[j] = binary[j + 2] = binary[j + 3] = true;
		}
		else if ( message[i] == 'c' )
		{
			//1 1 0 0
			binary[j] = binary[j + 1] = true;
			binary[j + 2] = binary[j + 3] = false;
		}
		else if ( message[i] == 'd' )
		{
			//1 1 0 1
			binary[j] = binary[j + 1] = binary[j + 3] = true;
			binary[j + 2] = false;
		}
		else if ( message[i] == 'e' )
		{
			//1 1 1 0
			binary[j] = binary[j + 1] = binary[j + 2] = true;
			binary[j + 3] = false;
		}
		else if ( message[i] == 'f' )
		{
			//1 1 1 1
			binary[j] = binary[j + 1] = binary[j + 2] = binary[j + 3] = true;
		}
	}
}


void Message::PrintHex ( void )
{
	for ( int i = 0; i < binaryLenght; i += 4 )
	{
		if ( binary[i] == false && binary[i + 1] == false && binary[i + 2] == false && binary[i + 3] == false )
		{
			cout << "0";
		}
		else if ( binary[i] == false && binary[i + 1] == false && binary[i + 2] == false && binary[i + 3] == true )
		{
			cout << "1";
		}
		else if ( binary[i] == false && binary[i + 1] == false && binary[i + 3] == false && binary[i + 2] == true )
		{
			cout << "2";
		}
		else if ( binary[i] == false && binary[i + 1] == false && binary[i + 2] == true && binary[i + 3] == true )
		{
			cout << "3";
		}
		else if ( binary[i] == false && binary[i + 2] == false && binary[i + 3] == false && binary[i + 1] == true )
		{
			cout << "4";
		}
		else if ( binary[i] == false && binary[i + 2] == false && binary[i + 1] == true && binary[i + 3] == true )
		{
			cout << "5";
		}
		else if ( binary[i] == false && binary[i + 3] == false && binary[i + 1] == true && binary[i + 2] == true)
		{
			cout << "6";
		}
		else if ( binary[i] == false && binary[i + 1] == true && binary[i + 2] == true && binary[i + 3] == true )
		{
			cout << "7";
		}
		else if ( binary[i] == true && binary[i + 1] == false && binary[i + 2] == false && binary[i + 3] == false )
		{
			cout << "8";
		}
		else if ( binary[i] == true && binary[i + 3] == true && binary[i + 1] == false && binary[i + 2] == false )
		{
			cout << "9";
		}
		else if ( binary[i] == true && binary[i + 2] == true && binary[i + 1] == false && binary[i + 3] == false )
		{
			cout << "a";
		}
		else if ( binary[i + 1] == false && binary[i] == true && binary[i + 2] == true && binary[i + 3] == true )
		{
			cout << "b";
		}
		else if ( binary[i] == true && binary[i + 1] == true && binary[i + 2] == false && binary[i + 3] == false )
		{
			cout << "c";
		}
		else if ( binary[i] == true && binary[i + 1] == true && binary[i + 3] == true && binary[i + 2] == false )
		{
			cout << "d";
		}
		else if ( binary[i] == true && binary[i + 1] == true && binary[i + 2] == true && binary[i + 3] == false )
		{
			cout << "e";
		}
		else if ( binary[i] == true && binary[i + 1] == true && binary[i + 2] == true && binary[i + 3] == true )
		{
			cout << "f";
		}
	}
}

Message::Message ( const Message  &message )
{
	this->binaryLenght = message.binaryLenght;
	this->binary = new bool [binaryLenght];

	for ( int i = 0; i < binaryLenght; i++ )
	{
		this->binary[i] = message.binary[i];
	}

	this->lenght = message.lenght;
	this->message = new unsigned char[lenght];

	for ( int i = 0; i < lenght; i++ )
	{
		this->message[i] = message.message[i];
	}
}

void Message::PrintASCII ( void )
{
	for ( int i = 0; i < lenght; i++ )
	{
		char ascii = 0;

		for ( int j = i * 8; j < i * 8 + 8; j++ )
		{
			if ( binary[j] == true )
			{
				ascii += 1 << 7 - ( j % 8 );
			}
		}

		message[i] = ascii;
	}

	for ( int i = 0; i < lenght; i++ )
		cout << message[i];
	cout << endl;
}

ostream& operator << ( ostream& stream, Message& message )
{
	for ( int i = 0; i < message.lenght; i++ )
	{
		char ascii = 0;

		for ( int j = i * 8; j < i * 8 + 8; j++ )
		{
			if ( message.binary[j] == true )
			{
				ascii += 1 << 7 - ( j % 8 );
			}
		}

		stream << ascii;
	}
		
	return stream;
}

istream& operator >> ( istream& stream, Message& message )
{
	message.lenght = 8;
	message.message = new unsigned char[8];

	for ( int i = 0; i < 8; i++ )	
	{
		stream >> message.message[i];
	}

	message.binaryLenght = 64;
        message.binary = new bool[ 64 ];

	message.AsciiToBinary();

//	 cout << "DEBUGGING: binary array after ascii to binary convertion:\n";
 //   	 for ( int i = 0; i < 64; i++ )
  //           cout << message.binary[i];
   //      cout << endl;


	return stream;
}
